package lol.clann.minecraft.springboot.plugin.bukkit.impl;

import lol.clann.minecraft.springboot.api.annotation.compatibility.CompatibilityChecked;
import lol.clann.minecraft.springboot.api.bukkit.utils.PluginUtils;
import lol.clann.minecraft.springboot.api.bukkit.utils.ServerUtils;
import lol.clann.minecraft.springboot.api.model.core.SBPConfig;
import lol.clann.minecraft.springboot.bukkit.utils.BukkitUtils;
import net.minecraft.server.v1_7_R4.MinecraftServer;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandMap;
import org.bukkit.craftbukkit.v1_7_R4.CraftServer;
import org.bukkit.scheduler.BukkitTask;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.concurrent.Callable;
import java.util.concurrent.Future;

/**
 *
 * @author pyz
 * @date 2019/5/6 11:30 PM
 */
@Service
@CompatibilityChecked
public class ServerUtilsImpl_all implements ServerUtils {

    @Autowired
    private PluginUtils pluginUtils;
    @Autowired
    private SBPConfig sbpConfig;

    @Override
    public void requirePrimaryThread() {
        if (!sbpConfig.isEnableThreadSaveMode()) {
            return;
        }
        requirePrimaryThreadStrict();
    }

    @Override
    public void requireNotPrimaryThread() {
        if (!sbpConfig.isEnableThreadSaveMode()) {
            return;
        }
        requireNotPrimaryThreadStrict();
    }


    @Override
    public CommandMap getCommandMap() {
        return ((CraftServer) getServer()).getCommandMap();
    }

    @Override
    public <T> T getNMSServer() {
        if (BukkitUtils.getBukkitVersionNumber() < 11400) {
            return (T) ((CraftServer) getServer()).getServer();
        } else {
            return (T) ((org.bukkit.craftbukkit.v1_14_R1.CraftServer) getServer()).getServer();
        }
    }

    @Override
    public double getTps() {
        long[] tickTimes;
        if (BukkitUtils.getBukkitVersionNumber() < 10800) {
            MinecraftServer ms = getNMSServer();
            tickTimes = ms.g;
        } else if (BukkitUtils.getBukkitVersionNumber() < 11300) {
            net.minecraft.server.v1_8_R3.MinecraftServer ms = getNMSServer();
            tickTimes = ms.h;
        } else if (BukkitUtils.getBukkitVersionNumber() < 11400) {
            net.minecraft.server.v1_13_R2.MinecraftServer ms = getNMSServer();
            tickTimes = ms.d;
        } else {
            net.minecraft.server.v1_14_R1.MinecraftServer ms = getNMSServer();
            tickTimes = ms.f;
        }
        double meanTickTime = mean(tickTimes) * 1e-6D;
        double meanTPS = Math.min(1000.0D / meanTickTime, 20.0D);
        return meanTPS;
    }

    @Override
    public boolean isRunning() {
        MinecraftServer ms = getNMSServer();
        return ms.isRunning();
    }

    @Override
    public <T> Future<T> callSyncMethod(Callable<T> callable) {
        return Bukkit.getScheduler().callSyncMethod(pluginUtils.getSelf(), callable);
    }

    @Override
    public void cancelTask(int taskId) {
        Bukkit.getScheduler().cancelTask(taskId);
    }

    @Override
    public BukkitTask runTask(Runnable task) throws IllegalArgumentException {
        return Bukkit.getScheduler().runTask(pluginUtils.getSelf(), task);
    }

    @Override
    public BukkitTask runTaskAsynchronously(Runnable task) throws IllegalArgumentException {
        return Bukkit.getScheduler().runTaskAsynchronously(pluginUtils.getSelf(), task);
    }

    @Override
    public BukkitTask runTaskLater(Runnable task, long dely) throws IllegalArgumentException {
        return Bukkit.getScheduler().runTaskLater(pluginUtils.getSelf(), task, dely);
    }

    @Override
    public BukkitTask runTaskLaterAsynchronously(Runnable task, long dely) throws IllegalArgumentException {
        return Bukkit.getScheduler().runTaskLaterAsynchronously(pluginUtils.getSelf(), task, dely);
    }

    @Override
    public BukkitTask runTaskTimer(Runnable task, long dely, long interval) throws IllegalArgumentException {
        return Bukkit.getScheduler().runTaskTimer(pluginUtils.getSelf(), task, dely, interval);
    }

    @Override
    public BukkitTask runTaskTimerAsynchronously(Runnable task, long dely, long interval) throws IllegalArgumentException {
        return Bukkit.getScheduler().runTaskTimerAsynchronously(pluginUtils.getSelf(), task, dely, interval);
    }

    private long mean(long[] values) {
        long sum = 0L;
        long[] var3 = values;
        int var4 = values.length;
        for (int var5 = 0; var5 < var4; ++var5) {
            long v = var3[var5];
            sum += v;
        }

        return sum / (long) values.length;
    }

}
